home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
utils
/
gdb36p4s.zoo
/
cplus-dem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-29
|
19KB
|
986 lines
/* Demangler for GNU C++
Copyright (C) 1989 Free Software Foundation, Inc.
written by James Clark (jjc@jclark.uucp)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This is for g++ 1.36.1 (November 6 version). It will probably
require changes for any other version.
Modified for g++ 1.36.2 (November 18 version). */
/* This file exports one function
char *cplus_demangle (const char *name, int ansi)
If NAME is a mangled function name produced by GNU C++, then
a pointer to a malloced string giving a C++ representation
of the name will be returned; otherwise NULL will be returned.
It is the caller's responsibility to free the string which
is returned.
If ANSI is non-zero, then ANSI qualifiers such as `const',
`void', and the ellipses operator `...' are output. Otherwise
they are not.
For example,
cplus_demangle ("_foo__1Ai")
returns
"A::foo(int)"
This file imports xmalloc and xrealloc, which are like malloc and
realloc except that they generate a fatal error if there is no
available memory. */
/* #define nounderscore 1 /* define this is names don't start with _ */
#include <stdio.h>
#include <ctype.h>
#ifdef USG
#include <memory.h>
#include <string.h>
#else
#include <strings.h>
#define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
#define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
#define strchr index
#define strrchr rindex
#endif
#ifndef __STDC__
#define const
#endif
#ifdef __STDC__
extern char *cplus_demangle (const char *type, int ansi);
#else
extern char *cplus_demangle ();
#endif
#ifdef __STDC__
extern char *xmalloc (int);
extern char *xrealloc (char *, int);
#else
extern char *xmalloc ();
extern char *xrealloc ();
#endif
static char **typevec = 0;
static int ntypes = 0;
static int typevec_size = 0;
static struct {
const char *in;
const char *out;
} optable[] = {
"new", " new",
"delete", " delete",
"ne", "!=",
"eq", "==",
"ge", ">=",
"gt", ">",
"le", "<=",
"lt", "<",
"plus", "+",
"minus", "-",
"mult", "*",
"convert", "+", /* unary + */
"negate", "-", /* unary - */
"trunc_mod", "%",
"trunc_div", "/",
"truth_andif", "&&",
"truth_orif", "||",
"truth_not", "!",
"postincrement", "++",
"postdecrement", "--",
"bit_ior", "|",
"bit_xor", "^",
"bit_and", "&",
"bit_not", "~",
"call", "()",
"cond", "?:",
"alshift", "<<",
"arshift", ">>",
"component", "->",
"indirect", "*",
"method_call", "->()",
"addr", "&", /* unary & */
"array", "[]",
"nop", "", /* for operator= */
};
/* Beware: these aren't '\0' terminated. */
typedef struct {
char *b; /* pointer to start of string */
char *p; /* pointer after last character */
char *e; /* pointer after end of allocated space */
} string;
#ifdef __STDC__
static void string_need (string *s, int n);
static void string_delete (string *s);
static void string_init (string *s);
static void string_clear (string *s);
static int string_empty (string *s);
static void string_append (string *p, const char *s);
static void string_appends (string *p, string *s);
static void string_appendn (string *p, const char *s, int n);
static void string_prepend (string *p, const char *s);
#if 0
static void string_prepends (string *p, string *s);
#endif
static void string_prependn (string *p, const char *s, int n);
static int get_count (const char **type, int *count);
static int do_args (const char **type, string *decl);
static int do_type (const char **type, string *result);
static int do_arg (const char **type, string *result);
static int do_args (const char **type, string *decl);
static void munge_function_name (string *name);
static void remember_type (const char *type, int len);
#else
static void string_need ();
static void string_delete ();
static void string_init ();
static void string_clear ();
static int string_empty ();
static void string_append ();
static void string_appends ();
static void string_appendn ();
static void string_prepend ();
static void string_prepends ();
static void string_prependn ();
static int get_count ();
static int do_args ();
static int do_type ();
static int do_arg ();
static int do_args ();
static void munge_function_name ();
static void remember_type ();
#endif
static int print_ansi_qualifiers;
char *
cplus_demangle (type, ansi)
const char *type;
int ansi;
{
string decl;
int n;
int success = 0;
int constructor = 0;
int const_flag = 0;
int i;
const char *p;
#ifndef LONGERNAMES
const char *premangle;
#endif
print_ansi_qualifiers = ansi;
if (type == NULL || *type == '\0')
return NULL;
#ifndef nounderscore
if (*type++ != '_')
return NULL;
#endif
p = type;
while (*p != '\0' && !(*p == '_' && p[1] == '_'))
p++;
if (*p == '\0')
{
/* destructor */
if (type[0] == '_' && type[1] == '$' && type[2] == '_')
{
int n = (strlen (type) - 3)*2 + 3 + 2 + 1;
char *tem = (char *) xmalloc (n);
strcpy (tem, type + 3);
strcat (tem, "::~");
strcat (tem, type + 3);
strcat (tem, "()");
return tem;
}
/* static data member */
if (*type != '_' && (p = strchr (type, '$')) != NULL)
{
int n = strlen (type) + 2;
char *tem = (char *) xmalloc (n);
memcpy (tem, type, p - type);
strcpy (tem + (p - type), "::");
strcpy (tem + (p - type) + 2, p + 1);
return tem;
}
/* virtual table */
if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
{
int n = strlen (type + 4) + 14 + 1;
char *tem = (char *) xmalloc (n);
strcpy (tem, type + 4);
strcat (tem, " virtual table");
return tem;
}
return NULL;
}
string_init (&decl);
if (p == type)
{
if (!isdigit (p[2]))
{
string_delete (&decl);
return NULL;
}
constructor = 1;
}
else
{
string_appendn (&decl, type, p - type);
munge_function_name (&decl);
}
p += 2;
#ifndef LONGERNAMES
premangle = p;
#endif
switch (*p)
{
case 'C':
/* a const member function */
if (!isdigit (p[1]))
{
string_delete (&decl);
return NULL;
}
p += 1;
const_flag = 1;
/* fall through */
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
n = 0;
do
{
n *= 10;
n += *p - '0';
p += 1;
}
while (isdigit (*p));
if (strlen (p) < n)
{
string_delete (&decl);
return NULL;
}
if (constructor)
{
string_appendn (&decl, p, n);
string_append (&decl, "::");
string_appendn (&decl, p, n);
}
else
{
string_prepend (&decl, "::");
string_prependn (&decl, p, n);
}
p += n;
#ifndef LONGERNAMES
remember_type (premangle, p - premangle);
#endif
success = do_args (&p, &decl);
if (const_flag)
string_append (&decl, " const");
break;
case 'F':
p += 1;
success = do_args (&p, &decl);
break;
}
for (i = 0; i < ntypes; i++)
if (typevec[i] != NULL)
free (typevec[i]);
ntypes = 0;
if (typevec != NULL)
{
free ((char *)typevec);
typevec = NULL;
typevec_size = 0;
}
if (success)
{
string_appendn (&decl, "", 1);
return decl.b;
}
else
{
string_delete (&decl);
return NULL;
}
}
static int
get_count (type, count)
const char **type;
int *count;
{
if (!isdigit (**type))
return 0;
*count = **type - '0';
*type += 1;
/* see flush_repeats in cplus-method.c */
if (isdigit (**type))